package com.wzg.gprintlib;

import android.Manifest;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.util.JsonReader;
import android.util.Log;
import android.view.View;

import com.gprinter.command.EscCommand;
import com.gprinter.command.LabelCommand;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Vector;

import static android.app.Activity.RESULT_OK;
import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_ATTACHED;
import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED;
import static com.wzg.gprintlib.Constant.ACTION_USB_PERMISSION;
import static com.wzg.gprintlib.DeviceConnFactoryManager.ACTION_QUERY_PRINTER_STATE;
import static com.wzg.gprintlib.DeviceConnFactoryManager.CONN_STATE_FAILED;

public class GPrintLib {

    private static final String TAG = "GPrintLib";
    private ThreadPool threadPool;
    private static final int REQUEST_CODE = 0x004;

    private static final int CONN_MOST_DEVICES = 0x11;
    /**
     * 连接状态断开
     */
    private static final int CONN_STATE_DISCONN = 0x007;

    ArrayList<String> per = new ArrayList<>();
    private PendingIntent mPermissionIntent;
    private String[] permissions = {
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.BLUETOOTH
    };
    /**
     * 使用打印机指令错误
     */
    private static final int PRINTER_COMMAND_ERROR = 0x008;

    private static final int CONN_PRINTER = 0x12;
    private int id = 0;
    private Context mContext;
    private GPrintLib.callBack GPrintCallBack;

    private String statusStr = "未连接";//连接状态信息。

    public GPrintLib(Context ctxt) {
        this.mContext = ctxt;
        this.checkPermission();
        this.requestPermission();
    }

    public void setCallBack(GPrintLib.callBack callBack) {
        this.GPrintCallBack = callBack;
    }

    public void onStart(Context ctxt) {
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(ACTION_USB_DEVICE_DETACHED);
        filter.addAction(ACTION_QUERY_PRINTER_STATE);
        filter.addAction(DeviceConnFactoryManager.ACTION_CONN_STATE);
        filter.addAction(ACTION_USB_DEVICE_ATTACHED);
        ctxt.registerReceiver(receiver, filter);
    }

    public void onStop(Context ctxt) {
        ctxt.unregisterReceiver(receiver);
    }

    public void onDestroy(Context ctxt) {

        DeviceConnFactoryManager.closeAllPort();
        if (threadPool != null) {
            threadPool.stopThreadPool();
            threadPool = null;
        }
    }

    private void checkPermission() {
        for (String permission : permissions) {
            if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(mContext, permission)) {
                per.add(permission);
            }
        }
    }


    private void requestPermission() {
        if (per.size() > 0) {
            String[] p = new String[per.size()];
            ActivityCompat.requestPermissions((Activity) mContext, per.toArray(p), REQUEST_CODE);
        }
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CONN_STATE_DISCONN:
                    if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] != null || !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
                        DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].closePort(id);
                        Utils.toast(mContext, mContext.getString(R.string.str_disconnect_success));
                    }
                    break;
                case PRINTER_COMMAND_ERROR:
                    Utils.toast(mContext, mContext.getString(R.string.str_choice_printer_command));
                    break;
                case CONN_PRINTER:
                    Utils.toast(mContext, mContext.getString(R.string.str_cann_printer));
                    break;
                default:
                    break;
            }
        }
    };

    /**
     * 获取连接状态信息
     *
     * @return
     */
    public String getStatusInfo() {
        return this.statusStr;
    }

    /**
     * 打印标签
     */
    public void startPrint(final String printContent) {
        threadPool = ThreadPool.getInstantiation();
        threadPool.addTask(new Runnable() {
            @Override
            public void run() {
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null ||
                        !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
                    mHandler.obtainMessage(CONN_PRINTER).sendToTarget();
                    return;
                }
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.TSC) {
                    try {
                        sendLabel(printContent);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    mHandler.obtainMessage(PRINTER_COMMAND_ERROR).sendToTarget();
                }
            }
        });
    }

    /**
     * 蓝牙连接
     */
    public void bluetoothConn(Activity activity) {
        activity.startActivityForResult(new Intent(activity, BluetoothDeviceList.class), Constant.BLUETOOTH_REQUEST_CODE);
    }

    /**
     * 断开连接
     */
    public void disConn() {
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null ||
                !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
            Utils.toast(mContext, mContext.getString(R.string.str_cann_printer));
            return;
        }
        mHandler.obtainMessage(CONN_STATE_DISCONN).sendToTarget();
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
//        super.onActivityResult( requestCode, resultCode, data );
        if (resultCode == RESULT_OK) {
            switch (requestCode) {
                /*蓝牙连接*/
                case Constant.BLUETOOTH_REQUEST_CODE: {
                    closeport();
                    /*获取蓝牙mac地址*/
                    String macAddress = data.getStringExtra(BluetoothDeviceList.EXTRA_DEVICE_ADDRESS);
                    /* 初始化话DeviceConnFactoryManager */
                    new DeviceConnFactoryManager.Build()
                            .setId(id)
                            /* 设置连接方式 */
                            .setConnMethod(DeviceConnFactoryManager.CONN_METHOD.BLUETOOTH)
                            /* 设置连接的蓝牙mac地址 */
                            .setMacAddress(macAddress)
                            .build();
                    /* 打开端口 */
                    Log.d(TAG, "onActivityResult: 连接蓝牙" + id);
                    threadPool = ThreadPool.getInstantiation();
                    threadPool.addTask(new Runnable() {
                        @Override
                        public void run() {
                            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].openPort();
                        }
                    });

                    break;
                }
                case CONN_MOST_DEVICES:
                    id = data.getIntExtra("id", -1);
                    if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] != null &&
                            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
//                        tvConnState.setText(getString(R.string.str_conn_state_connected) + "\n" + getConnDeviceInfo());
                        statusStr = mContext.getString(R.string.str_conn_state_connected) + "\n" + getConnDeviceInfo();
                    } else {
//                        tvConnState.setText(getString(R.string.str_conn_state_disconnect));
                        statusStr = mContext.getString(R.string.str_conn_state_disconnect);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    private String getConnDeviceInfo() {
        String str = "";
        DeviceConnFactoryManager deviceConnFactoryManager = DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id];
        if (deviceConnFactoryManager != null
                && deviceConnFactoryManager.getConnState()) {
            if ("USB".equals(deviceConnFactoryManager.getConnMethod().toString())) {
                str += "USB\n";
                str += "USB Name: " + deviceConnFactoryManager.usbDevice().getDeviceName();
            } else if ("WIFI".equals(deviceConnFactoryManager.getConnMethod().toString())) {
                str += "WIFI\n";
                str += "IP: " + deviceConnFactoryManager.getIp() + "\t";
                str += "Port: " + deviceConnFactoryManager.getPort();
            } else if ("BLUETOOTH".equals(deviceConnFactoryManager.getConnMethod().toString())) {
                str += "BLUETOOTH\n";
                str += "MacAddress: " + deviceConnFactoryManager.getMacAddress();
            } else if ("SERIAL_PORT".equals(deviceConnFactoryManager.getConnMethod().toString())) {
                str += "SERIAL_PORT\n";
                str += "Path: " + deviceConnFactoryManager.getSerialPortPath() + "\t";
                str += "Baudrate: " + deviceConnFactoryManager.getBaudrate();
            }
        }
        return (str);
    }

    /**
     * 重新连接回收上次连接的对象，避免内存泄漏
     */
    private void closeport() {
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] != null && DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort != null) {
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].reader.cancel();
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort.closePort();
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort = null;
        }
    }


    /**
     * 发送标签
     */
    void sendLabel(String printContent) throws Exception {
        JSONArray array = new JSONArray(printContent);

        LabelCommand tsc = new LabelCommand();
        /* 设置标签尺寸，按照实际尺寸设置 */
        tsc.addSize(80, 90);
        /* 设置标签间隙，按照实际尺寸设置，如果为无间隙纸则设置为0 */
        tsc.addGap(1);
        /* 设置打印方向 */
        tsc.addDirection(LabelCommand.DIRECTION.FORWARD, LabelCommand.MIRROR.NORMAL);
        /* 开启带Response的打印，用于连续打印 */
        tsc.addQueryPrinterStatus(LabelCommand.RESPONSE_MODE.ON);
        /* 设置原点坐标 */
        tsc.addReference(0, 0);
        /* 撕纸模式开启 */
        tsc.addTear(EscCommand.ENABLE.ON);
        /* 清除打印缓冲区 */
        tsc.addCls();
        for (int i = 0; i < array.length(); i++) {
            JSONObject object = array.getJSONObject(i);

            int x = object.getInt("x");
            int y = object.getInt("y");
            String type = object.getString("type");
            String content = object.getString("content");

            String rotation = object.getString("rotation");
            Log.d("tracy", "obj" + i + " =" + object.toString());
            LabelCommand.ROTATION r = LabelCommand.ROTATION.valueOf(rotation);

            if ("Text".equals(type)) {
                String fontmul = object.getString("fontmul");
                LabelCommand.FONTMUL f = LabelCommand.FONTMUL.valueOf(fontmul);
                tsc.addText(x, y, LabelCommand.FONTTYPE.SIMPLIFIED_CHINESE, r, f, f,
                        content);
            } else if ("QRCode".equals(type)) {
                int cellwidth = object.getInt("cellwidth");
                tsc.addQRCode(x, y, LabelCommand.EEC.LEVEL_H, cellwidth, r, content);

            }

        }
        /* 绘制简体中文 */
//        tsc.addText(10, 2, LabelCommand.FONTTYPE.SIMPLIFIED_CHINESE, LabelCommand.ROTATION.ROTATION_0, LabelCommand.FONTMUL.MUL_1, LabelCommand.FONTMUL.MUL_1,
//                "Welcome to use SMARNET printer");
        /* 绘制图片 */
//        Bitmap b = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.gprinter);
//        tsc.addBitmap(10, 20, LabelCommand.BITMAP_MODE.OVERWRITE, 300, b);

//        tsc.addQRCode(50, 50, LabelCommand.EEC.LEVEL_H, 12, LabelCommand.ROTATION.ROTATION_0, printContent);
        /* 绘制一维条码 */
//        tsc.add1DBarcode(10, 450, LabelCommand.BARCODETYPE.CODE128, 100, LabelCommand.READABEL.EANBEL, LabelCommand.ROTATION.ROTATION_0, "SMARNET");

//        tsc.addText(50, 380, LabelCommand.FONTTYPE.SIMPLIFIED_CHINESE, LabelCommand.ROTATION.ROTATION_0, LabelCommand.FONTMUL.MUL_1, LabelCommand.FONTMUL.MUL_1,
//                printContent);

//        tsc.addText(100, 580, LabelCommand.FONTTYPE.TRADITIONAL_CHINESE, LabelCommand.ROTATION.ROTATION_0, LabelCommand.FONTMUL.MUL_1, LabelCommand.FONTMUL.MUL_1,
//                "繁體字");

//        tsc.addText(190, 580, LabelCommand.FONTTYPE.KOREAN, LabelCommand.ROTATION.ROTATION_0, LabelCommand.FONTMUL.MUL_1, LabelCommand.FONTMUL.MUL_1,
//                "한국어");

        /* 打印标签 */
        tsc.addPrint(1, 1);
        /* 打印标签后 蜂鸣器响 */

        tsc.addSound(2, 100);
        tsc.addCashdrwer(LabelCommand.FOOT.F5, 255, 255);
        Vector<Byte> datas = tsc.getCommand();
        /* 发送数据 */
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null) {
            Log.d(TAG, "sendLabel: 打印机为空");
            return;
        }
        DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendDataImmediately(datas);
    }

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {

                /* Usb连接断开、蓝牙连接断开广播 */
                case ACTION_USB_DEVICE_DETACHED:
                    mHandler.obtainMessage(CONN_STATE_DISCONN).sendToTarget();
                    break;
                case DeviceConnFactoryManager.ACTION_CONN_STATE:
                    int state = intent.getIntExtra(DeviceConnFactoryManager.STATE, -1);
                    int deviceId = intent.getIntExtra(DeviceConnFactoryManager.DEVICE_ID, -1);
                    switch (state) {
                        case DeviceConnFactoryManager.CONN_STATE_DISCONNECT:
                            if (id == deviceId) {

//                                tvConnState.setText( context.getString( R.string.str_conn_state_disconnect ) );
                                Log.d("tracy", context.getString(R.string.str_conn_state_disconnect));
                                statusStr = context.getString(R.string.str_conn_state_disconnect);
                                if (GPrintCallBack != null) {
                                    GPrintCallBack.onConect(DeviceConnFactoryManager.CONN_STATE_DISCONNECT, context.getString(R.string.str_conn_state_disconnect));
                                }
                            }
                            break;
                        case DeviceConnFactoryManager.CONN_STATE_CONNECTING:
//                            tvConnState.setText( getString( R.string.str_conn_state_connecting ) );
                            Log.d("tracy", context.getString(R.string.str_conn_state_connecting));
                            if (GPrintCallBack != null) {
                                GPrintCallBack.onConect(DeviceConnFactoryManager.CONN_STATE_CONNECTING, context.getString(R.string.str_conn_state_connecting));
                            }
                            statusStr = context.getString(R.string.str_conn_state_connecting);
                            break;
                        case DeviceConnFactoryManager.CONN_STATE_CONNECTED:
//                            tvConnState.setText( getString( R.string.str_conn_state_connected ) + "\n" + getConnDeviceInfo() );
                            Log.d("tracy", context.getString(R.string.str_conn_state_connected) + "\n" + getConnDeviceInfo());
                            if (GPrintCallBack != null) {
                                GPrintCallBack.onConect(DeviceConnFactoryManager.CONN_STATE_CONNECTED, context.getString(R.string.str_conn_state_connected) + "\n" + getConnDeviceInfo());
                            }
                            statusStr = context.getString(R.string.str_conn_state_connected) + "\n" + getConnDeviceInfo();
                            /*
                             *                            if(DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].connMethod== DeviceConnFactoryManager.CONN_METHOD.WIFI){
                             *                                wificonn=true;
                             *                                if(keepConn==null) {
                             *                                    keepConn = new KeepConn();
                             *                                    keepConn.start();
                             *                                }
                             *                            }
                             */
                            break;
                        default:
                            break;
                    }
                    break;

                default:
                    break;
            }
        }
    };

    public interface callBack {
        void onConect(int state, String connInfo);
    }

}
